{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "#Agentic RAG\n",
    "Agentic Retrieval-Augmented Generation (RAG) is an advanced framework designed to handle complex information retrieval tasks using a network of intelligent agents. These agents collaborate to perform nuanced tasks such as synthesizing information from multiple documents, summarizing content, and comparing data points across various sources. Agentic RAG infuses autonomy and intelligence into traditional retrieval systems, enabling them to act as passive tools and proactive entities that understand context, evaluate data quality, and make informed decisions."
   ],
   "metadata": {
    "id": "MT4Z9xRQVUM2"
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Blog\n",
    "\n",
    "For a detailed explanation of agentic rag, check out  [blog post on Medium](https://aksdesai1998.medium.com/662bac582da9).\n"
   ],
   "metadata": {
    "id": "dbzbP8U3WDov"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "mstdPht-oONc"
   },
   "outputs": [],
   "source": [
    "# install the required dependencies\n",
    "%%capture --no-stderr\n",
    "%pip install -U --quiet langchain-community tiktoken langchain-openai langchainhub lancedb  langchain langgraph langchain-text-splitters langchain_openai gradio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Rieiaeu9posq",
    "outputId": "c6806878-ccda-484a-9820-aef37c4bd700"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:root:USER_AGENT environment variable not set, consider setting it to identify your requests.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import getpass\n",
    "import gradio as gr\n",
    "from typing import Annotated, Literal, Sequence, TypedDict\n",
    "from langchain import hub\n",
    "from langchain_community.document_loaders import WebBaseLoader\n",
    "from langchain_community.vectorstores import LanceDB\n",
    "from langchain_core.messages import BaseMessage, HumanMessage\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "from langchain_openai import OpenAIEmbeddings, ChatOpenAI\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "from langchain.tools.retriever import create_retriever_tool\n",
    "from langgraph.graph.message import add_messages\n",
    "from langgraph.graph import END, StateGraph\n",
    "from langgraph.graph.message import add_messages\n",
    "from langgraph.prebuilt import ToolExecutor, ToolNode, tools_condition"
   ]
  },
  {
   "cell_type": "code",
   "source": [],
   "metadata": {
    "id": "YbaPskMdVc2h"
   },
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true,
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "wpwx86tgorLG",
    "outputId": "b2216382-c340-44f0-d70e-0c8e980fac1a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Setting queue=True in a Colab notebook requires sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n",
      "\n",
      "Colab notebook detected. This cell will run indefinitely so that you can see errors and logs. To turn off, set debug=False in launch().\n",
      "Running on public URL: https://1300bf30884d92867e.gradio.live\n",
      "\n",
      "This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div><iframe src=\"https://1300bf30884d92867e.gradio.live\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Debug output: {'agent': {'messages': [AIMessage(content='The PM Gati Shakti National Master Plan (NMP) is an ambitious initiative launched by the Government of India aimed at improving infrastructure development across the country. Launched by Prime Minister Narendra Modi, the plan seeks to integrate the planning and coordination of various infrastructure projects across different sectors and ministries.\\n\\nThe core objective of the Gati Shakti NMP is to enhance multi-modal connectivity and reduce logistics costs by bringing together rail, road, air, and waterways projects under a single, unified framework. This holistic approach is intended to boost economic growth, create jobs, and promote regional connectivity.\\n\\nThe plan utilizes digital technology to map and synchronize projects, ensuring that all related departments and stakeholders are aligned, which helps in eliminating bottlenecks, improving project execution speed, and enhancing overall efficiency. The Gati Shakti NMP is seen as a transformative step towards making India a global manufacturing hub and improving the ease of doing business.', response_metadata={'finish_reason': 'stop'}, id='run-8bc90fb4-007b-4384-9320-35c3621eb9b8-0')]}}\n",
      "Extracted content: The PM Gati Shakti National Master Plan (NMP) is an ambitious initiative launched by the Government of India aimed at improving infrastructure development across the country. Launched by Prime Minister Narendra Modi, the plan seeks to integrate the planning and coordination of various infrastructure projects across different sectors and ministries.\n",
      "\n",
      "The core objective of the Gati Shakti NMP is to enhance multi-modal connectivity and reduce logistics costs by bringing together rail, road, air, and waterways projects under a single, unified framework. This holistic approach is intended to boost economic growth, create jobs, and promote regional connectivity.\n",
      "\n",
      "The plan utilizes digital technology to map and synchronize projects, ensuring that all related departments and stakeholders are aligned, which helps in eliminating bottlenecks, improving project execution speed, and enhancing overall efficiency. The Gati Shakti NMP is seen as a transformative step towards making India a global manufacturing hub and improving the ease of doing business.\n",
      "Debug output: {'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_AE3GmC26FUSF63Nb4NhJCSMb', 'function': {'arguments': '{\"query\": \"steps for export import procedure\"}', 'name': 'retrieve_blog_posts'}, 'type': 'function'}, {'index': 1, 'id': 'call_B56lmGd2JIHRDCdxf9Um9Ml7', 'function': {'arguments': '{\"query\": \"customs import export procedure\"}', 'name': 'retrieve_blog_posts'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls'}, id='run-2c42f15d-390b-4509-8b23-fbc6d1fb203d-0', tool_calls=[{'name': 'retrieve_blog_posts', 'args': {'query': 'steps for export import procedure'}, 'id': 'call_AE3GmC26FUSF63Nb4NhJCSMb'}, {'name': 'retrieve_blog_posts', 'args': {'query': 'customs import export procedure'}, 'id': 'call_B56lmGd2JIHRDCdxf9Um9Ml7'}])]}}\n",
      "Extracted content: \n",
      "Debug output: {'retrieve': {'messages': [ToolMessage(content='<</Title(Microsoft Word - CUSTOMS IMPORT EXPORT PROCEDURES _final_) /Author(Admin) /Creator(��\\x00M\\x00i\\x00c\\x00r\\x00o\\x00s\\x00o\\x00f\\x00t\\x00�\\x00 \\x00W\\x00o\\x00r\\x00d\\x00 \\x00f\\x00o\\x00r\\x00 \\x00M\\x00i\\x00c\\x00r\\x00o\\x00s\\x00o\\x00f\\x00t\\x00 \\x003\\x006\\x005)\\n\\n<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">Microsoft Word - CUSTOMS IMPORT EXPORT PROCEDURES _final_</rdf:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>Admin</rdf:li></rdf:Seq></dc:creator></rdf:Description>\\n\\nendobj\\r\\n118 0 obj\\r\\n<</Subtype/Link/Rect[ 354.97 540.84 462.41 561.54] /BS<</W 0>>/F 4/A<</Type/Action/S/URI/URI(https://www.indiafilings.com/learn/zero-rated-supply-under-gst/) >>/StructParent 32>>\\r\\nendobj\\r\\n119 0 obj\\n\\nEP\\x12t1Ԗ�m�l1�PI�����ٲW$��`�B[C��\\x1e�2�R�ν7ȗ���C�3�a���\\x1fZ��U\\x7f��\\x10�5y<:', name='retrieve_blog_posts', id='8714e8e7-ed08-4452-8d1f-621f4f25af81', tool_call_id='call_AE3GmC26FUSF63Nb4NhJCSMb'), ToolMessage(content='<</Title(Microsoft Word - CUSTOMS IMPORT EXPORT PROCEDURES _final_) /Author(Admin) /Creator(��\\x00M\\x00i\\x00c\\x00r\\x00o\\x00s\\x00o\\x00f\\x00t\\x00�\\x00 \\x00W\\x00o\\x00r\\x00d\\x00 \\x00f\\x00o\\x00r\\x00 \\x00M\\x00i\\x00c\\x00r\\x00o\\x00s\\x00o\\x00f\\x00t\\x00 \\x003\\x006\\x005)\\n\\n<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">Microsoft Word - CUSTOMS IMPORT EXPORT PROCEDURES _final_</rdf:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>Admin</rdf:li></rdf:Seq></dc:creator></rdf:Description>\\n\\nCdTa�x\\t&��A\\x0eb�1����\\x0errMM�q�\\x7f1Q2cҩ0de�˂���>�\\x1b\\x12�\\x19?�\\x0fa�L���Q\\n\\nt\\'�P��h\\x13��u\\u05eex����|^���(I�$�%\\x1f�Q%�.\\x19U�B��jY��\\x16�?\\x19\\x19�\\x0e�$��W�BԸ���\\x1ck��\\x19��l!K�\\x05�!z�\\x1dq\\x12�\\x1d�v��]�P\"\\x11ROC��\\x14', name='retrieve_blog_posts', id='8a56ed96-cd2a-4846-a60d-258e6430aa79', tool_call_id='call_B56lmGd2JIHRDCdxf9Um9Ml7')]}}\n",
      "Debug output: {'generate': {'messages': [\"I don't know.\"]}}\n",
      "Debug output: {'agent': {'messages': [AIMessage(content='The term \"RCMC\" stands for Registration Cum Membership Certificate. It is a certificate that is provided by the Export Promotion Councils (EPCs) or commodity boards in India. An RCMC is issued to exporters dealing in products registered with these agencies. Holding an RCMC is mandatory for exporters to avail benefits under the Foreign Trade Policy like duty drawback, concessions, and other support.\\n\\nHere are some key points about RCMC:\\n\\n1. **Purpose**: The RCMC is used to certify that an exporter is registered with the respective EPC and is eligible for various benefits under the export-import policy.\\n\\n2. **Validity**: Typically, an RCMC is valid for five years.\\n\\n3. **Application**: Exporters must apply for an RCMC with the relevant EPC that pertains to their main line of business. If the exporter wishes to export items that are not covered by any EPC, they can obtain an RCMC from the Federation of Indian Export Organisations (FIEO).\\n\\n4. **Benefits**: With an RCMC, exporters can participate in international trade fairs, get sponsorship for trade delegations, and access market development assistance among other benefits.\\n\\n5. **Renewal and Cancellation**: The certificate needs to be renewed upon expiry. It can also be cancelled or suspended if the holder fails to abide by the regulatory requirements.\\n\\nIf you need detailed information or specific guidance related to obtaining an RCMC, please let me know!', response_metadata={'finish_reason': 'stop'}, id='run-4fa5e544-510a-4140-984c-89dedd855e71-0')]}}\n",
      "Extracted content: The term \"RCMC\" stands for Registration Cum Membership Certificate. It is a certificate that is provided by the Export Promotion Councils (EPCs) or commodity boards in India. An RCMC is issued to exporters dealing in products registered with these agencies. Holding an RCMC is mandatory for exporters to avail benefits under the Foreign Trade Policy like duty drawback, concessions, and other support.\n",
      "\n",
      "Here are some key points about RCMC:\n",
      "\n",
      "1. **Purpose**: The RCMC is used to certify that an exporter is registered with the respective EPC and is eligible for various benefits under the export-import policy.\n",
      "\n",
      "2. **Validity**: Typically, an RCMC is valid for five years.\n",
      "\n",
      "3. **Application**: Exporters must apply for an RCMC with the relevant EPC that pertains to their main line of business. If the exporter wishes to export items that are not covered by any EPC, they can obtain an RCMC from the Federation of Indian Export Organisations (FIEO).\n",
      "\n",
      "4. **Benefits**: With an RCMC, exporters can participate in international trade fairs, get sponsorship for trade delegations, and access market development assistance among other benefits.\n",
      "\n",
      "5. **Renewal and Cancellation**: The certificate needs to be renewed upon expiry. It can also be cancelled or suspended if the holder fails to abide by the regulatory requirements.\n",
      "\n",
      "If you need detailed information or specific guidance related to obtaining an RCMC, please let me know!\n"
     ]
    }
   ],
   "source": [
    "# Function to set environment variables securely\n",
    "def _set_env(key: str):\n",
    "    if key not in os.environ:\n",
    "        os.environ[key] = getpass.getpass(f\"{key}:\")\n",
    "\n",
    "\n",
    "_set_env(\"OPENAI_API_KEY\")\n",
    "\n",
    "# (Optional) For tracing\n",
    "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"False\"\n",
    "_set_env(\"LANGCHAIN_API_KEY\")\n",
    "\n",
    "\n",
    "# upload the data based on your usecase\n",
    "\n",
    "urls = [\n",
    "    \"https://content.dgft.gov.in/Website/CIEP.pdf\",\n",
    "    \"https://content.dgft.gov.in/Website/GAE.pdf\",\n",
    "    \"https://content.dgft.gov.in/Website/HTE.pdf\",\n",
    "]\n",
    "\n",
    "\n",
    "docs = [WebBaseLoader(url).load() for url in urls]\n",
    "docs_list = [item for sublist in docs for item in sublist]\n",
    "\n",
    "text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(\n",
    "    chunk_size=100, chunk_overlap=50\n",
    ")\n",
    "doc_splits = text_splitter.split_documents(docs_list)\n",
    "\n",
    "# Add to  lancedb as vectordb\n",
    "\n",
    "vectorstore = LanceDB.from_documents(\n",
    "    documents=doc_splits,\n",
    "    embedding=OpenAIEmbeddings(),\n",
    ")\n",
    "retriever = vectorstore.as_retriever()\n",
    "\n",
    "\n",
    "# create the tools\n",
    "retriever_tool = create_retriever_tool(\n",
    "    retriever,\n",
    "    \"retrieve_blog_posts\",\n",
    "    \"Search and return information about customs import export procedure,GST & EXPORTS , How to export\",\n",
    ")\n",
    "\n",
    "tools = [retriever_tool]\n",
    "tool_executor = ToolExecutor(tools)\n",
    "\n",
    "\n",
    "class AgentState(TypedDict):\n",
    "    messages: Annotated[Sequence[BaseMessage], add_messages]\n",
    "\n",
    "\n",
    "def grade_documents(state) -> Literal[\"generate\", \"rewrite\"]:\n",
    "    class grade(BaseModel):\n",
    "        binary_score: str = Field(description=\"Relevance score 'yes' or 'no'\")\n",
    "\n",
    "    model = ChatOpenAI(temperature=0, model=\"gpt-4-0125-preview\", streaming=True)\n",
    "    llm_with_tool = model.with_structured_output(grade)\n",
    "    prompt = PromptTemplate(\n",
    "        template=\"\"\"You are a grader assessing relevance of a retrieved document to a user question. \\n\n",
    "        Here is the retrieved document: \\n\\n {context} \\n\\n\n",
    "        Here is the user question: {question} \\n\n",
    "        If the document contains keyword(s) or semantic meaning related to the user question, grade it as relevant. \\n\n",
    "        Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.\"\"\",\n",
    "        input_variables=[\"context\", \"question\"],\n",
    "    )\n",
    "    chain = prompt | llm_with_tool\n",
    "\n",
    "    messages = state[\"messages\"]\n",
    "    last_message = messages[-1]\n",
    "    question = messages[0].content\n",
    "    docs = last_message.content\n",
    "\n",
    "    scored_result = chain.invoke({\"question\": question, \"context\": docs})\n",
    "    score = scored_result.binary_score\n",
    "\n",
    "    return \"generate\" if score == \"yes\" else \"rewrite\"\n",
    "\n",
    "\n",
    "def agent(state):\n",
    "    messages = state[\"messages\"]\n",
    "    model = ChatOpenAI(temperature=0, streaming=True, model=\"gpt-4-turbo\")\n",
    "    model = model.bind_tools(tools)\n",
    "    response = model.invoke(messages)\n",
    "    return {\"messages\": [response]}\n",
    "\n",
    "\n",
    "def rewrite(state):\n",
    "    messages = state[\"messages\"]\n",
    "    question = messages[0].content\n",
    "    msg = [\n",
    "        HumanMessage(\n",
    "            content=f\"\"\" \\n\n",
    "            Look at the input and try to reason about the underlying semantic intent / meaning. \\n\n",
    "            Here is the initial question:\n",
    "            \\n ------- \\n\n",
    "            {question}\n",
    "            \\n ------- \\n\n",
    "            Formulate an improved question: \"\"\",\n",
    "        )\n",
    "    ]\n",
    "    model = ChatOpenAI(temperature=0, model=\"gpt-4-0125-preview\", streaming=True)\n",
    "    response = model.invoke(msg)\n",
    "    return {\"messages\": [response]}\n",
    "\n",
    "\n",
    "def generate(state):\n",
    "    messages = state[\"messages\"]\n",
    "    question = messages[0].content\n",
    "    last_message = messages[-1]\n",
    "    docs = last_message.content\n",
    "\n",
    "    prompt = hub.pull(\"rlm/rag-prompt\")\n",
    "    llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0, streaming=True)\n",
    "\n",
    "    def format_docs(docs):\n",
    "        return \"\\n\\n\".join(doc.page_content for doc in docs)\n",
    "\n",
    "    rag_chain = prompt | llm | StrOutputParser()\n",
    "    response = rag_chain.invoke({\"context\": docs, \"question\": question})\n",
    "    return {\"messages\": [response]}\n",
    "\n",
    "\n",
    "workflow = StateGraph(AgentState)\n",
    "workflow.add_node(\"agent\", agent)\n",
    "retrieve = ToolNode([retriever_tool])\n",
    "workflow.add_node(\"retrieve\", retrieve)\n",
    "workflow.add_node(\"rewrite\", rewrite)\n",
    "workflow.add_node(\"generate\", generate)\n",
    "workflow.set_entry_point(\"agent\")\n",
    "workflow.add_conditional_edges(\n",
    "    \"agent\", tools_condition, {\"tools\": \"retrieve\", END: END}\n",
    ")\n",
    "workflow.add_conditional_edges(\"retrieve\", grade_documents)\n",
    "workflow.add_edge(\"generate\", END)\n",
    "workflow.add_edge(\"rewrite\", \"agent\")\n",
    "graph = workflow.compile()\n",
    "\n",
    "\n",
    "def process_message(user_message):\n",
    "    inputs = {\"messages\": [(\"user\", user_message)]}\n",
    "    content_output = None\n",
    "    for output in graph.stream(inputs):\n",
    "        print(f\"Debug output: {output}\")  # Debugging line to print the output\n",
    "        if \"agent\" in output and \"messages\" in output[\"agent\"]:\n",
    "            messages = output[\"agent\"][\"messages\"]\n",
    "            if messages and hasattr(messages[0], \"content\"):\n",
    "                content_output = messages[0].content  # Accessing attribute directly\n",
    "                print(f\"Extracted content: {content_output}\")  # Print extracted content\n",
    "    return content_output if content_output else \"No relevant output found.\"\n",
    "\n",
    "\n",
    "# Define example questions to guide the user\n",
    "example_questions = [\n",
    "    \"explain me in short what is PM Gati Shakti National Master Plan (NMP)?\"\n",
    "]\n",
    "\n",
    "# Create a Gradio interface\n",
    "iface = gr.Interface(\n",
    "    fn=process_message,\n",
    "    inputs=\"text\",\n",
    "    outputs=\"text\",\n",
    "    title=\"Agentic RAG \",\n",
    "    description=\"Enter a message to query related to export import .\",\n",
    "    examples=example_questions,\n",
    ")\n",
    "\n",
    "# Launch the Gradio app\n",
    "iface.launch(debug=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "JjmUVVn1TdH0"
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "source": [
    "#some quetions for testing\n",
    "explain me in short what is PM Gati Shakti National Master Plan (NMP)?\n",
    "\n",
    "what is Zero Rating of Exports?\n",
    "\n",
    "what is Export Inspection Council of India?\n",
    "\n",
    "please give us some Details of some of the major initiatives /schemes please ?"
   ],
   "metadata": {
    "id": "c921cw61mPdh"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "k6Tq9E1Lqwtj"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}